Java 8元空间(Metaspace)

元空间(Metaspace):

相信许多Java开发者都见过“java.lang.OutOfMemoryError: PermGen space”问题,这通常是类加载器相关的内存泄漏以及新类加载器的创建导致的,一般出现于代码热部署时。相对于正式产品,该问题在开发机上出现的频率更高,通常“问题”是默认值太低了, 常用的解决方法是将其设置为256MB或更高。

PermGen space的全称是Permanent Generation space,是指JVM永久保存区域,这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和和存放Instance的Heap区域不同,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。这种错误常见在web服务器对JSP进行pre compile的时候。JVM 种类有很多(如Oralce-Sun Hotspot, Oralce JRockit, IBM J9, Taobao JVM)。Oracle-Sun Hotspot才有PermGen space,JRockit以及J9没有这个区域。

随着JAVA8时代的来临,新增一种使用本地内存来存储类元数据信息称之为元空间(Metaspace),JVM永久区被元空间(Metaspace)替换(JEP 122), 与Oracle JRockit 和IBM JVM’s很相似。JVM参数 -XX:PermSize 和 -XX:MaxPermSize被XX:MetaSpaceSize 和 -XX:MaxMetaspaceSize代替,如果使用了-XX:PermSize 和 -XX:MaxPermSize启动时会发出警告。。 这意味着不会再有java.lang.OutOfMemoryError: PermGen问题,也不再需要你进行调优及监控内存空间的使用。

Metaspace 内存分配模型

  • 大部分类元数据都在本地内存中分配。
  • 用于描述类元数据的“klasses”已经被移除。

Metaspace 容量

  • 默认情况下,类元数据只受可用的本地内存限制(容量取决于是32位或是64位操作系统的可用虚拟内存大小)。
  • 新参数(MaxMetaspaceSize)用于限制本地内存分配给类元数据的大小。如果没有指定这个参数,元空间会在运行时根据需要动态调整。

Metaspace 垃圾回收

  • 对于僵死的类及类加载器的垃圾回收将在元数据使用达到“MaxMetaspaceSize”参数的设定值时进行。
  • 适时地监控和调整元空间对于减小垃圾回收频率和减少延时是很有必要的。持续的元空间垃圾回收说明,可能存在类、类加载器导致的内存泄漏或是大小设置不合适。

Java 堆内存的影响

一些杂项数据已经移到Java堆空间中。升级到JDK8之后,会发现Java堆 空间有所增长。

Metaspace 监控

元空间的使用情况可以从HotSpot1.8的详细GC日志输出中看到。